home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 11 - 1995 / 11.02 Feb 95 / Yenta / Erics C++ Libraries / Interface Classes / CPPScrollArea.cp < prev    next >
Encoding:
Text File  |  1996-04-04  |  25.9 KB  |  970 lines  |  [TEXT/KAHL]

  1. /********************************************************* DEFINITION
  2.     DATE:    10/17/93
  3.     AUTHOR: Eric R. Rosé
  4.     
  5.     CLASS:  CPPScrollArea
  6.     
  7.     SUPERCLASS: CPPVisualObject
  8.     
  9.         This C++ class manages a scrollable area
  10.     
  11. ********************************************************************/
  12.  
  13.  
  14. #include <CPPWindow.h>
  15. #include <CPPScrollArea.h>
  16. #include <Commands.h>
  17. #include <mathTools.h>
  18.  
  19. /*-----------------------------------------------------------------*/
  20. /*---------------------- CALLBACK VARIABLES -----------------------*/
  21. /*-----------------------------------------------------------------*/
  22.  
  23.     // Initialize the class member variables used in the callbacks
  24.     CPPScrollArea *CPPScrollArea::gCurrentArea = NULL;
  25.     ControlHandle CPPScrollArea::gVScroll = NULL;
  26.     ControlHandle CPPScrollArea::gHScroll = NULL;
  27.  
  28. /*-----------------------------------------------------------------*/
  29. /*-------------------------- GLOBALS ------------------------------*/
  30. /*-----------------------------------------------------------------*/
  31.  
  32.     extern    Rect        kEmptyRect;
  33.     extern    RGBColor    RGBBlack;
  34.  
  35. /*-----------------------------------------------------------------*/
  36. /*------------------------ PUBLIC METHODS -------------------------*/
  37. /*-----------------------------------------------------------------*/
  38.  
  39.  
  40.     CPPScrollArea::CPPScrollArea (CPPWindow *OurWindow,
  41.                                   Rect *ViewArea,
  42.                                   Rect *DestArea,
  43.                                   Boolean UseHScroll,
  44.                                   Boolean UseVScroll,
  45.                                   short hStep, short vStep) :
  46.                    CPPVisualObject (OurWindow, ViewArea, TRUE, FALSE)
  47.     {
  48.         MakeCPPScrollArea (OurWindow, ViewArea, DestArea, 
  49.                            UseHScroll, UseVScroll, hStep, vStep);
  50.     
  51.     }
  52.  
  53. /*-----------------------------------------------------------------*/
  54.           
  55.     CPPScrollArea::CPPScrollArea (CPPWindow *OurWindow,
  56.                                   Boolean UseHScroll,
  57.                                   Boolean UseVScroll,
  58.                                   short hStep, short vStep) :
  59.                 CPPVisualObject (OurWindow,
  60.                                  &((OurWindow->GetWindow())->portRect), 
  61.                                    TRUE, FALSE)
  62.     {
  63.         Rect    ViewRect;
  64.         Rect    DestRect;
  65.  
  66.         if (OurWindow)
  67.           {
  68.               ViewRect = (OurWindow->GetWindow())->portRect;
  69.               ViewRect.left--; ViewRect.top--;
  70.               SetRect (&DestRect, 0, 0, kPageWidth, kPageHeight);
  71.             MakeCPPScrollArea (OurWindow, &ViewRect, &DestRect, 
  72.                                UseHScroll, UseVScroll, hStep, vStep);
  73.           }
  74.     }
  75.  
  76. /*-----------------------------------------------------------------*/
  77.     
  78.     CPPScrollArea::~CPPScrollArea (void)
  79.     {
  80.     
  81.     }
  82.     
  83. /*-----------------------------------------------------------------*/
  84.  
  85.     char     *CPPScrollArea::ClassName (void)
  86.     {
  87.         return "CPPScrollArea";
  88.     }
  89.  
  90. /*-----------------------------------------------------------------*/
  91.  
  92.     Boolean    CPPScrollArea::DoCommand (short commandID)
  93.     /* do a command associated with a menu */
  94.     {
  95.         switch (commandID) {
  96.             case kCmdCut :
  97.                 DoCut();
  98.                 break;
  99.             case kCmdCopy :    
  100.                 DoCopy();
  101.                 break;
  102.             case kCmdPaste :
  103.                 DoPaste();
  104.                 break;
  105.             case kCmdSelectAll :
  106.                 DoSelectAll();
  107.                 break;
  108.             case kCmdClear :
  109.                 DoClear();
  110.                 break;
  111.             default:
  112.                 return FALSE;
  113.                 break;
  114.         }
  115.         
  116.         return TRUE;
  117.     }
  118.  
  119. /*-----------------------------------------------------------------*/
  120.  
  121.     void    CPPScrollArea::DoCut (void)
  122.     /* cut the currently selected contents */
  123.     /* SUBCLASS SHOULD OVERRIDE */
  124.     {
  125.     
  126.     }
  127.  
  128. /*-----------------------------------------------------------------*/
  129.  
  130.     void    CPPScrollArea::DoCopy (void)
  131.     /* copy the currently selected contents */
  132.     /* SUBCLASS SHOULD OVERRIDE */
  133.     {
  134.     
  135.     }
  136.  
  137. /*-----------------------------------------------------------------*/
  138.  
  139.     void    CPPScrollArea::DoPaste (void)
  140.     /* paste new data into the area */
  141.     /* SUBCLASS SHOULD OVERRIDE */
  142.     {
  143.     
  144.     }
  145.  
  146. /*-----------------------------------------------------------------*/
  147.  
  148.     void    CPPScrollArea::DoClear (void)
  149.     /* clear the currently selected contents */
  150.     /* SUBCLASS SHOULD OVERRIDE */
  151.     {
  152.         
  153.     }
  154.  
  155. /*-----------------------------------------------------------------*/
  156.  
  157.     void    CPPScrollArea::DoSelectAll (void)
  158.     /* select the entire scroll area */
  159.     {
  160.         RemoveSelection();
  161.         
  162.         MakeSelection (&this->destRect);
  163.     }
  164.  
  165. /*-----------------------------------------------------------------*/
  166.  
  167.     void    CPPScrollArea::RemoveSelection(void)
  168.     /* forget about the current selection */
  169.     {        
  170.         if (this->hasSelection)
  171.           {
  172.               HiliteSelection(FALSE);
  173.               this->selRect = kEmptyRect;
  174.               this->hasSelection = FALSE;
  175.           }
  176.     }
  177.         
  178. /*-----------------------------------------------------------------*/
  179.  
  180.     void    CPPScrollArea::MakeSelection (Rect *newSelection)
  181.     /* create a new selection area; deselect any which previously */
  182.     /* existed */
  183.     {
  184.         if (this->hasSelection)
  185.           RemoveSelection();
  186.         this->selRect = *newSelection;
  187.         this->hasSelection = TRUE;
  188.         HiliteSelection(TRUE);
  189.     }
  190.  
  191. /*-----------------------------------------------------------------*/
  192.  
  193.     void    CPPScrollArea::HiliteSelection (Boolean doHilight)
  194.     /* SUBCLASS SHOULD OVERRIDE */
  195.     /* Turn the hilighting of the selection on or off depending on */
  196.     /* the value of doHilight */
  197.     {
  198.         
  199.     }
  200.     
  201. /*-----------------------------------------------------------------*/
  202.  
  203.     void    CPPScrollArea::IdleSelection (void)
  204.     /* Perform whatever periodic updating is needed to hilight */
  205.     /* the selection */
  206.     /* SUBCLASS SHOULD OVERRIDE */
  207.     {
  208.         
  209.     }
  210.  
  211. /*-----------------------------------------------------------------*/
  212.  
  213.     void    CPPScrollArea::Activate (Boolean nowActive)
  214.     /* activate or deactivate the controls in the scroll area */
  215.     {
  216.         short    HiliteValue = (nowActive) ? 0 : 255;
  217.         
  218.         CPPVisualObject::Activate(nowActive);
  219.         
  220.         AdjustScrollBar();
  221.         
  222.         if (this->VScroll)
  223.           HiliteControl (this->VScroll, HiliteValue);
  224.         if (this->HScroll)
  225.           HiliteControl (this->HScroll, HiliteValue);
  226.     }
  227.     
  228. /*-----------------------------------------------------------------*/
  229.     
  230.     Boolean CPPScrollArea::DoClick (EventRecord *theEvent)
  231.     /* handle a click in the scroll area */
  232.     {
  233.         WindowPtr    theWindow;
  234.         short        code, part;
  235.         ControlHandle    hitControl;
  236.         Point        myPt = theEvent->where;
  237.         Boolean        shiftDown = (theEvent->modifiers & shiftKey) ? TRUE : FALSE;
  238.         
  239.         if (!IsVisible()) return FALSE;
  240.         
  241.           code = FindWindow(theEvent->where, &theWindow);
  242.           if (theWindow == this->owningWindow)
  243.             {
  244.               Global2Local (&myPt);
  245.             part = FindControl(myPt, theWindow, &hitControl);
  246.             
  247.             // now respond to the click
  248.             if (hitControl)        // if they clicked in a scrollbar
  249.               {
  250.                 if (hitControl == this->HScroll)
  251.                   DoHScroller (myPt, part);
  252.                 else
  253.                 if (hitControl ==  this->VScroll)
  254.                   DoVScroller (myPt, part);
  255.                 else
  256.                   return FALSE;
  257.               }
  258.             else                // if they clicked in the TE area
  259.               {
  260.                   if (PtInRect (myPt, &this->areaRect))
  261.                     {
  262.                           gVScroll = this->VScroll;
  263.                           gHScroll = this->HScroll;
  264.                           gCurrentArea = this;
  265.                         Local2Area (&myPt);
  266.                       return DoScrollAreaClick(myPt, theEvent->modifiers);
  267.                     }
  268.                   else
  269.                     return FALSE;
  270.               }    
  271.             }
  272.     }
  273.     
  274. /*-----------------------------------------------------------------*/
  275.     
  276.     Boolean    CPPScrollArea::DoScrollAreaClick (Point clickPt, short modifiers)
  277.     /* handle a click in the scroll area; clickPt is in area coordinates */
  278.     /* SUBCLASS SHOULD OVERRIDE */
  279.     {
  280.         // default behavior; scroll the area automatically as long
  281.         // as the mouse is down
  282.         while (StillDown())
  283.           AutoScroll();
  284.           
  285.         return TRUE;
  286.     }
  287.  
  288. /*-----------------------------------------------------------------*/
  289.     
  290.     void    CPPScrollArea::DoIdle (void)
  291.     {
  292.         if (this->hasSelection)
  293.           IdleSelection ();
  294.     }
  295.     
  296. /*-----------------------------------------------------------------*/
  297.  
  298.     Rect    *CPPScrollArea::GetAreaRect (void)
  299.     {
  300.         return &this->areaRect;
  301.     }
  302.  
  303. /*-----------------------------------------------------------------*/
  304.  
  305.     Rect    *CPPScrollArea::GetBounds (void)
  306.     /* return a rectangle in window coordinates which encloses */
  307.     /* the whole visible scroll area and its controls*/
  308.     {
  309.         this->bounds = kEmptyRect;
  310.         
  311.         if (this->isVisible)
  312.           {
  313.               this->bounds = this->areaRect;
  314.             if (this->HScroll)
  315.               UnionRect (&((**this->HScroll).contrlRect), &this->bounds, &this->bounds);
  316.             if (this->VScroll)
  317.               UnionRect (&((**this->VScroll).contrlRect), &this->bounds, &this->bounds);
  318.           }
  319.  
  320.         return &this->bounds;
  321.     }
  322.     
  323. /*-----------------------------------------------------------------*/
  324.  
  325.     void    CPPScrollArea::DrawContents (void)
  326.     /* Draw the data in the window */
  327.     /* SUBCLASS MUST OVERRIDE */
  328.     {
  329.         RGBColor    VColor = {65535, 65535, 65535};
  330.         RGBColor    HColor = {65535, 65535, 65535};
  331.         long        x, y;
  332.         
  333.         for (x = this->destRect.left; x <= this->destRect.right; x+= this->hStep)
  334.           {
  335.               HColor.red = HColor.green = HColor.blue =  HColor.blue - 65535 / AreaWidth();
  336.             RGBForeColor (&HColor);
  337.             MoveTo (x, this->viewRect.top);
  338.             LineTo (x, this->viewRect.bottom);
  339.           }
  340.         
  341.         for (y = this->destRect.top; y <= this->destRect.bottom; y += this->vStep)
  342.           {
  343.               VColor.red = VColor.green = VColor.blue = VColor.blue -= 65535 / AreaHeight();
  344.             RGBForeColor (&VColor);
  345.             MoveTo (this->viewRect.left, y);
  346.             LineTo (this->viewRect.right, y);
  347.           }
  348.     
  349.         RGBForeColor (&RGBBlack);
  350.     }
  351.     
  352. /*-----------------------------------------------------------------*/
  353.  
  354.     void    CPPScrollArea::Draw (void)
  355.     /* set the origin and clipping rect and call the user routine */
  356.     /* to draw the contents of the scroll area */
  357.     {
  358.         RgnHandle    oldClip = NewRgn(),
  359.                     newClip = NewRgn();
  360.         Rect        tempRect = *GetBounds();
  361.  
  362.         // draw the frame and the scrollbars
  363.         if (this->VScroll)
  364.           Draw1Control (this->VScroll);
  365.         if (this->HScroll)
  366.           Draw1Control (this->HScroll);
  367.         FrameRect (&tempRect);
  368.  
  369.         // set the origin so the contents can drawn naturally
  370.         SetOrigin(this->viewRect.left-this->areaRect.left, 
  371.                   this->viewRect.top-this->areaRect.top);
  372.     
  373.         // clip drawing to the visible area
  374.         GetClip (oldClip);
  375.         tempRect = this->viewRect;
  376.         InsetRect (&tempRect, 1, 1);
  377.         if (this->HScroll)
  378.           tempRect.bottom++;    
  379.         if (this->VScroll)
  380.           tempRect.right++;
  381.         RectRgn (newClip, &tempRect);
  382.         SectRgn (newClip, oldClip, newClip);
  383.         SetClip (newClip);
  384.         
  385.         // call the user routines to draw the contents and selection
  386.         DrawContents();
  387.         if (this->hasSelection)
  388.           HiliteSelection(TRUE);
  389.         
  390.         // restore the clip region and coordinate systems
  391.         
  392.         SetClip (oldClip);
  393.         DisposeRgn(oldClip);
  394.         DisposeRgn(newClip);
  395.         SetOrigin(0, 0);
  396.     }
  397.     
  398. /*-----------------------------------------------------------------*/
  399.  
  400.     void    CPPScrollArea::MakeVisible (Boolean nowVisible)
  401.     {
  402.         Rect    boundsRect = *GetBounds();
  403.     
  404.         InsetRect (&boundsRect, -1, -1);
  405.         // exit if it is already in the desired state
  406.         if (nowVisible == IsVisible())
  407.           return;
  408.         
  409.         CPPVisualObject::MakeVisible (nowVisible);
  410.  
  411.         // if it is currently invisible, erase it;
  412.         // in either case, invalidate the area to force a redraw
  413.         if (!IsVisible())
  414.           {
  415.             EraseRect (&boundsRect);
  416.             if (this->VScroll)
  417.               HideControl(VScroll);
  418.             if (this->HScroll)
  419.               HideControl(HScroll);
  420.           }
  421.         else
  422.           {
  423.             if (this->VScroll)
  424.               ShowControl(VScroll);
  425.             if (this->HScroll)
  426.               ShowControl(HScroll);
  427.             this->Draw();
  428.           }
  429.           
  430.         InvalRect(&boundsRect);
  431.     }
  432.  
  433. /*-----------------------------------------------------------------*/
  434.  
  435.     void    CPPScrollArea::TargetHilite (Boolean makeTarget)
  436.     /* do any hiliting necessary to indicate that the scroll area is */
  437.     /* now the target */
  438.     /* SUBCLASS MAY OVERRIDE */
  439.     {
  440.         this->Activate(makeTarget);
  441.         
  442.         CPPVisualObject::TargetHilite(makeTarget);
  443.     }
  444.  
  445. /*-----------------------------------------------------------------*/
  446.                                    
  447.     void    CPPScrollArea::SetHorizontalStep (short stepSize)
  448.     /* change the step size of the horizontal scroll bar; adjust */
  449.     /* the current value of the scrollbar as necessary */
  450.     {
  451.         short    oldValue, oldMax, newMax;
  452.         
  453.         if (this->hStep != stepSize)
  454.           {
  455.               this->hStep = stepSize;
  456.               if (this->HScroll)
  457.                 {
  458.                     oldValue = GetCtlValue(this->HScroll);
  459.                     oldMax = GetCtlMax(this->HScroll);
  460.                     
  461.                     SetCtlMax (this->HScroll, newMax = AreaWidth());
  462.                     SetCtlValue (this->HScroll, newMax * oldValue / oldMax);
  463.                 }
  464.           }
  465.     }
  466.  
  467. /*-----------------------------------------------------------------*/
  468.  
  469.     void    CPPScrollArea::SetVerticalStep    (short stepSize)
  470.     /* change the step size of the vertical scroll bar; adjust */
  471.     /* the current value of the scrollbar as necessary */
  472.     {
  473.         short    oldValue, oldMax, newMax;
  474.         
  475.         if (this->vStep != stepSize)
  476.           {
  477.               this->vStep = stepSize;
  478.               if (this->VScroll)
  479.                 {
  480.                     oldValue = GetCtlValue(this->VScroll);
  481.                     oldMax = GetCtlMax(this->VScroll);
  482.                     
  483.                     SetCtlMax (this->VScroll, newMax = AreaHeight());
  484.                     SetCtlValue (this->VScroll, newMax * oldValue / oldMax);
  485.                 }
  486.           }
  487.     }
  488.  
  489. /*-----------------------------------------------------------------*/
  490.  
  491.     void     CPPScrollArea::MoveScrollArea (void)
  492.     {
  493.         long    ScrollValue,
  494.                 height, i, j, 
  495.                 HScrollDiff = 0, VScrollDiff = 0,
  496.                 OldScroll, NewScroll;
  497.         RgnHandle    updateRgn = NewRgn(),
  498.                     oldClipRgn = NewRgn();
  499.         Rect    tempRect = this->areaRect;
  500.         
  501.         InsetRect (&tempRect, 1, 1);
  502.         
  503.         if (this->VScroll)
  504.           {
  505.               tempRect.right++;
  506.               OldScroll = this->viewRect.top - this->destRect.top;
  507.               ScrollValue = GetCtlValue (this->VScroll);
  508.               NewScroll = ScrollValue * this->vStep;
  509.               VScrollDiff = OldScroll - NewScroll;
  510.           }          
  511.  
  512.         if (this->HScroll)
  513.           {
  514.               tempRect.bottom++;
  515.               OldScroll = this->viewRect.left - this->destRect.left;
  516.               ScrollValue = GetCtlValue (this->HScroll);
  517.               NewScroll = ScrollValue * this->hStep;
  518.               HScrollDiff = OldScroll - NewScroll;
  519.           }          
  520.  
  521.         // do the scrolling, if any is required
  522.         if (VScrollDiff + HScrollDiff != 0)
  523.           ScrollRect(&tempRect, HScrollDiff, VScrollDiff, updateRgn);
  524.         OffsetRect (&this->viewRect, -HScrollDiff, -VScrollDiff);
  525.         OffsetRgn (updateRgn, viewRect.left - areaRect.left, 
  526.                               viewRect.top - areaRect.top); 
  527.         
  528.         
  529.         GetClip (oldClipRgn);
  530.         SectRgn (updateRgn, oldClipRgn, updateRgn);
  531.         SetClip (updateRgn);
  532.           
  533.         this->Draw();
  534.         
  535.         SetClip (oldClipRgn);
  536.         DisposeRgn(updateRgn);
  537.         DisposeRgn(oldClipRgn);
  538.     }
  539.  
  540. /*-----------------------------------------------------------------*/
  541. /*---------------------- PROTECTED METHODS ------------------------*/
  542. /*-----------------------------------------------------------------*/
  543.  
  544.     void    CPPScrollArea::ResizeContent (short newWidth, short newHeight)
  545.     {
  546.         Rect    VCRect, HCRect, GrowRect, ViewRect, DestRect;
  547.         Rect    PRect;
  548.         
  549.         if (this->owningWindow)
  550.           {
  551.               // resize the actual on-screen area;
  552.               this->areaRect.right = this->areaRect.left + 1 +
  553.                   newWidth - ((this->VScroll) ? 15 : 0);
  554.               this->areaRect.bottom = this->areaRect.top + 1 +
  555.                   newHeight - ((this->HScroll) ? 15 : 0);
  556.           
  557.               // set the new size of the view area
  558.               this->viewRect.right = this->viewRect.left + 
  559.                   (this->areaRect.right - this->areaRect.left);
  560.               this->viewRect.bottom = this->viewRect.top + 
  561.                   (this->areaRect.bottom - this->areaRect.top);
  562.                             
  563.               // move and resize the controls
  564.               if (this->HScroll)
  565.                 {
  566.                     HideControl (this->HScroll);
  567.                     MoveControl (this->HScroll, this->areaRect.left, this->areaRect.bottom);
  568.                     SizeControl (this->HScroll, (this->areaRect.right - this->areaRect.left) + 1, 16);
  569.                     ShowControl (this->HScroll);
  570.                 }
  571.  
  572.               if (this->VScroll)
  573.                 {
  574.                     HideControl (this->VScroll);
  575.                     MoveControl (this->VScroll, this->areaRect.right, this->areaRect.top);
  576.                     SizeControl (this->VScroll, 16, (this->areaRect.bottom - this->areaRect.top) + 1);
  577.                     ShowControl (this->VScroll);
  578.                 }
  579.                             
  580.               // adjust the positions of everything
  581.               if (viewRect.right > destRect.right)
  582.                 OffsetRect (&this->viewRect, destRect.right - viewRect.right, 0);
  583.               if (viewRect.bottom > destRect.bottom)
  584.                 OffsetRect (&this->viewRect, 0, destRect.bottom - viewRect.bottom);
  585.               AdjustScrollBar();
  586.           }
  587.     }
  588.     
  589. /*-----------------------------------------------------------------*/
  590.  
  591.     void    CPPScrollArea::MoveContent (short newH, short newV)
  592.     {
  593.         Rect        vRect, dRect, bRect = *GetBounds();
  594.         short        deltaH = newH - bRect.left,
  595.                      deltaV = newV - bRect.top;
  596.             
  597.         // move the visible area
  598.         OffsetRect (&this->areaRect, deltaH, deltaV);
  599.         
  600.         // move the vertical scroll bar
  601.         if (this->VScroll)
  602.           {
  603.               vRect = (*this->VScroll)->contrlRect;
  604.               MoveControl (this->VScroll, vRect.left + deltaH, 
  605.                                            vRect.top + deltaV);
  606.           }
  607.         
  608.         // move the horizontal scroll bar
  609.         if (this->HScroll)
  610.           {
  611.               dRect = (*this->HScroll)->contrlRect;
  612.               MoveControl (this->HScroll, dRect.left + deltaH, 
  613.                                            dRect.top + deltaV);
  614.           }
  615.     }
  616.     
  617. /*-----------------------------------------------------------------*/
  618. /*----------------------- PRIVATE METHODS -------------------------*/
  619. /*-----------------------------------------------------------------*/
  620.  
  621.     pascal void CPPScrollArea::Scroll_Up (ControlHandle theControl, short ctlPart)
  622.     /* this method serves as a callback routine for TrackControl; */
  623.     /* It forces the area to scroll up 1 line */
  624.     {
  625.         if (theControl && (GetCtlValue(theControl) - 1 >= GetCtlMin(theControl)))
  626.           {
  627.               SetCtlValue (theControl, GetCtlValue (theControl)-1);
  628.               gCurrentArea->MoveScrollArea();
  629.           }    
  630.     }
  631.  
  632. /*-----------------------------------------------------------------*/
  633.  
  634.     pascal void CPPScrollArea::Scroll_Down (ControlHandle theControl, 
  635.                                         short ctlPart)
  636.     /* this method serves as a callback routine for TrackControl; */
  637.     /* It forces the area to scroll down 1 line */
  638.     {
  639.         if (theControl && (GetCtlValue(theControl) + 1 <= GetCtlMax(theControl)))
  640.           {
  641.               SetCtlValue (theControl, GetCtlValue (theControl)+1);
  642.               gCurrentArea->MoveScrollArea();
  643.           }    
  644.     }
  645.  
  646. /*-----------------------------------------------------------------*/
  647.  
  648.     pascal void CPPScrollArea::Scroll_Left (ControlHandle theControl, 
  649.                                         short ctlPart)
  650.     /* this method serves as a callback routine for TrackControl; */
  651.     /* It forces the area to scroll left 1 line */
  652.     {
  653.         if (theControl && (GetCtlValue(theControl) - 1 >= GetCtlMin(theControl)))
  654.           {
  655.               SetCtlValue (theControl, GetCtlValue (theControl)-1);
  656.               gCurrentArea->MoveScrollArea();
  657.           }    
  658.     }
  659.  
  660. /*-----------------------------------------------------------------*/
  661.  
  662.     pascal void CPPScrollArea::Scroll_Right (ControlHandle theControl, 
  663.                                         short ctlPart)
  664.     /* this method serves as a callback routine for TrackControl; */
  665.     /* It forces the area to scroll right 1 line */
  666.     {
  667.         if (theControl && (GetCtlValue(theControl) + 1 <= GetCtlMax(theControl)))
  668.           {
  669.               SetCtlValue (theControl, GetCtlValue (theControl)+1);
  670.               gCurrentArea->MoveScrollArea();
  671.           }    
  672.     }
  673.  
  674. /*-----------------------------------------------------------------*/
  675.  
  676.     void    CPPScrollArea::Area2Local (Point *thePoint)
  677.     /* convert from scroll area coordinates to window coordinates */
  678.     {
  679.         thePoint->h -= this->areaRect.left;
  680.         thePoint->v -= this->areaRect.top;
  681.     }
  682.  
  683. /*-----------------------------------------------------------------*/
  684.  
  685.     void    CPPScrollArea::Local2Area (Point *thePoint)
  686.     /* convert from window coordinates to scroll area coordinates */
  687.     {
  688.         thePoint->h += this->areaRect.left;
  689.         thePoint->v += this->areaRect.top;
  690.     }
  691.  
  692. /*-----------------------------------------------------------------*/
  693.  
  694.     void    CPPScrollArea::Area2Global (Point *thePoint)
  695.     /* convert from scroll area coordinates to global coordinates */
  696.     {
  697.         WindowPtr    theWindow = this->owningWindow;
  698.  
  699.         if (theWindow)
  700.           {
  701.               // first convert it from area to local
  702.               Area2Local (thePoint);
  703.               // then convert from local to global
  704.               thePoint->h -= theWindow->portRect.left;
  705.               thePoint->v -= theWindow->portRect.top;
  706.           }
  707.     }
  708.  
  709. /*-----------------------------------------------------------------*/
  710.  
  711.     void    CPPScrollArea::Global2Area (Point *thePoint)
  712.     /* convert from global coordinates to scroll area coordinates */
  713.     {
  714.         WindowPtr    theWindow = this->owningWindow;
  715.         
  716.         if (theWindow)
  717.           {
  718.               // first convert from global to local
  719.               thePoint->h += theWindow->portRect.left;
  720.               thePoint->v += theWindow->portRect.top;
  721.               // then convert from local to area
  722.               Local2Area (thePoint);
  723.           }    
  724.     }
  725.  
  726. /*-----------------------------------------------------------------*/
  727.  
  728.     void CPPScrollArea::AutoScroll (void)
  729.     /* This routine will cause the area to scroll to follow the */
  730.     /* mouse */
  731.     {
  732.         Point        mouseLoc;
  733.                 
  734.         GetMouse (&mouseLoc);
  735.         
  736.         if (mouseLoc.v < this->areaRect.top)
  737.           Scroll_Up (gVScroll, inUpButton);
  738.         else
  739.           if (mouseLoc.v > this->areaRect.bottom)
  740.             Scroll_Down (gVScroll, inDownButton);
  741.  
  742.         if (mouseLoc.h > this->areaRect.right)
  743.           Scroll_Right (gHScroll, inDownButton);
  744.         else
  745.           if (mouseLoc.h < this->areaRect.left)
  746.             Scroll_Left (gHScroll, inUpButton);
  747.     }
  748.  
  749. /*-----------------------------------------------------------------*/
  750.  
  751.     void    CPPScrollArea::VPageScroll (long part, long direction)
  752.     /* Scroll the text 1 page either up or down */
  753.     {
  754.         Point    tempPt;
  755.         short    newValue, page;
  756.         
  757.         if (this->VScroll)
  758.           {
  759.               GetMouse (&tempPt);
  760.               while (StillDown())
  761.                 {
  762.                     if (TestControl(this->VScroll, tempPt) == part)
  763.                       {
  764.                           page = direction * (ViewHeight() - 1);
  765.                           newValue = GetCtlValue (this->VScroll) + page;
  766.                           SetCtlValue (this->VScroll, newValue);
  767.                           MoveScrollArea();
  768.                       }
  769.                     GetMouse (&tempPt);
  770.                 }    
  771.           }
  772.     }
  773.     
  774. /*-----------------------------------------------------------------*/
  775.  
  776.     void    CPPScrollArea::HPageScroll (long part, long direction)
  777.     /* Scroll the text 1 page either left or right */
  778.     {
  779.         Point    tempPt;
  780.         short    newValue, page;
  781.         
  782.         if (this->HScroll)
  783.           {
  784.               GetMouse (&tempPt);
  785.               while (StillDown())
  786.                 {
  787.                     if (TestControl(this->HScroll, tempPt) == part)
  788.                       {
  789.                           page = direction * (ViewWidth()-1);
  790.                           newValue = GetCtlValue (this->HScroll) + page;
  791.                           SetCtlValue (this->HScroll, newValue);
  792.                           MoveScrollArea();
  793.                       }
  794.                     GetMouse (&tempPt);
  795.                 }    
  796.           }
  797.     }
  798.  
  799. /*-----------------------------------------------------------------*/
  800.  
  801.      long    CPPScrollArea::AreaWidth (void)
  802.      /* return the number of horizontal lines in the entire scroll area */
  803.      {
  804.          return ((this->destRect.right - this->destRect.left) / this->hStep);
  805.      }
  806.  
  807. /*-----------------------------------------------------------------*/
  808.  
  809.      long    CPPScrollArea::AreaHeight (void)
  810.       /* return the number of vertical lines in the entire scroll area */
  811.     {
  812.          return ((this->destRect.bottom - this->destRect.top) / this->vStep);
  813.      }
  814.  
  815. /*-----------------------------------------------------------------*/
  816.  
  817.      long    CPPScrollArea::ViewWidth (void)
  818.      /* return the number of horizontal lines in the visible scroll area */
  819.     {
  820.          return ((this->viewRect.right - this->viewRect.left) / this->hStep);
  821.      }
  822.  
  823. /*-----------------------------------------------------------------*/
  824.  
  825.      long    CPPScrollArea::ViewHeight (void)
  826.       /* return the number of vertical lines in the visible scroll area */
  827.      {
  828.          return ((this->viewRect.bottom - this->viewRect.top) / this->vStep);
  829.      }
  830.  
  831. /*-----------------------------------------------------------------*/
  832.  
  833.     void    CPPScrollArea::AdjustScrollBar (void)
  834.     /* This procedure turns the scroll bars off if there are fewer */
  835.     /* lines than space for lines, and turns them on if there are more */
  836.     {        
  837.         if (this->HScroll)
  838.           SetCtlMax (this->HScroll, Max(0, AreaWidth() - ViewWidth()));
  839.         if (this->VScroll)
  840.           SetCtlMax (this->VScroll, Max(0, AreaHeight() - ViewHeight()));
  841.     }
  842.  
  843. /*-----------------------------------------------------------------*/
  844.  
  845.     void CPPScrollArea::DoVScroller (Point clickPt, short part)
  846.     /* Handle a click in the vertical scroll bar */
  847.     {
  848.         long    Result;
  849.         
  850.         gCurrentArea = this;
  851.         
  852.         if (this->VScroll)
  853.           {
  854.             switch (part) {
  855.                 case inUpButton     :
  856.                     Result = TrackControl(this->VScroll, clickPt, 
  857.                                           (ProcPtr)Scroll_Up);
  858.                     break;
  859.                 case inDownButton    :
  860.                     Result = TrackControl(this->VScroll, clickPt, 
  861.                                           (ProcPtr)Scroll_Down);
  862.                     break;
  863.                 case inPageUp        :
  864.                     VPageScroll (part, -1);
  865.                     break;
  866.                 case inPageDown        :
  867.                     VPageScroll (part, 1);
  868.                     break;
  869.                 case inThumb        :
  870.                     TrackControl (this->VScroll, clickPt, NULL);
  871.                     MoveScrollArea();
  872.                     break;
  873.             }
  874.           }
  875.     }
  876.     
  877. /*-----------------------------------------------------------------*/
  878.  
  879.     void CPPScrollArea::DoHScroller (Point clickPt, short part)
  880.     /* Handle a click in the horizontal scroll bar */
  881.     {
  882.         long    Result;
  883.  
  884.         gCurrentArea = this;
  885.         
  886.         if (this->HScroll)
  887.           {
  888.             switch (part) {
  889.                 case inUpButton     :
  890.                     Result = TrackControl(this->HScroll, clickPt, 
  891.                                           (ProcPtr)Scroll_Left);
  892.                     break;
  893.                 case inDownButton    :
  894.                     Result = TrackControl(this->HScroll, clickPt, 
  895.                                           (ProcPtr)Scroll_Right);
  896.                     break;
  897.                 case inPageUp        :
  898.                     HPageScroll (part, -1);
  899.                     break;
  900.                 case inPageDown        :
  901.                     HPageScroll (part, 1);
  902.                     break;
  903.                 case inThumb        :
  904.                     TrackControl (this->HScroll, clickPt, NULL);
  905.                     MoveScrollArea();
  906.                     break;
  907.             }
  908.           }
  909.     }
  910.  
  911. /*-----------------------------------------------------------------*/
  912.  
  913.     void    CPPScrollArea::MakeCPPScrollArea (CPPWindow *OurWindow, 
  914.                                               Rect *ViewArea, 
  915.                                               Rect *DestArea, 
  916.                                                  Boolean UseHScroll, 
  917.                                                  Boolean UseVScroll,
  918.                                                  short    hStep, 
  919.                                                  short vStep)
  920.     {
  921.         Rect    tempRect;
  922.         
  923.         // set the control step size
  924.         this->hStep = hStep;
  925.         this->vStep = vStep;
  926.         
  927.         /* figure out where the area and view rectangles are */
  928.         this->destRect = *DestArea;
  929.         this->areaRect = *ViewArea;
  930.         this->areaRect.right -= (UseVScroll) ? 15 : 0;
  931.         this->areaRect.bottom -= (UseHScroll) ? 15 : 0;
  932.         SetRect (&this->viewRect, 0, 0, 
  933.                  areaRect.right - areaRect.left,
  934.                  areaRect.bottom - areaRect.top);
  935.         this->selRect = kEmptyRect;
  936.         this->hasSelection = FALSE;
  937.         
  938.         // create the vertical scroll bar
  939.         if (UseVScroll)
  940.           {
  941.               SetRect (&tempRect, areaRect.right, areaRect.top-1,
  942.                        areaRect.right + 16, areaRect.bottom+1);
  943.               this->VScroll = NewControl (OurWindow->GetWindow(),
  944.                                           &tempRect, "\pVScroll",
  945.                                           TRUE, 0, 0, 
  946.                                           AreaHeight() - ViewHeight(),
  947.                                           scrollBarProc, 13);
  948.           }
  949.         else this->VScroll = NULL;
  950.           
  951.         // create the horizontal scroll bar
  952.         if (UseHScroll)
  953.           {
  954.               SetRect (&tempRect, areaRect.left-1, areaRect.bottom,
  955.                        areaRect.right+1, areaRect.bottom + 16);
  956.               this->HScroll = NewControl (OurWindow->GetWindow(),
  957.                                           &tempRect, "\pHScroll",
  958.                                           TRUE, 0, 0, 
  959.                                           AreaWidth() - ViewWidth(),
  960.                                           scrollBarProc, 13);
  961.           }
  962.         else this->HScroll = NULL;
  963.                   
  964.     }
  965.     
  966.     
  967.     
  968.     
  969.     
  970.